package com.wunong.smart.collection.domain.service.impl;

import com.google.common.base.Preconditions;
import com.wunong.smart.collection.application.request.BaseCollectionRequest;
import com.wunong.smart.collection.application.request.CancelCollectionRequest;
import com.wunong.smart.collection.application.request.CollectRequest;
import com.wunong.smart.collection.domain.model.CollectionDomain;
import com.wunong.smart.collection.domain.service.CollectionDomainService;
import com.wunong.smart.collection.domain.state.CollectionStateFactory;
import com.wunong.smart.collection.repository.CollectionRepository;
import com.wunong.smart.domain.component.lock.DistributeLockSupport;
import com.wunong.smart.domain.platform.common.BizSource;
import lombok.Getter;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author create by zealot.zt
 */
public class CollectionDomainServiceImpl implements CollectionDomainService {

    @Resource
    protected DistributeLockSupport distributeLockSupport;

    @Getter
    @Resource
    protected CollectionRepository collectionRepository;

    @Getter
    @Resource
    protected CollectionStateFactory collectionStateFactory;

    @Override
    public Long collect(CollectRequest request) {
        return distributeLockSupport.withLock(() -> {
            BizSource source = request.getSource();

            CollectionDomain domain = collectionRepository.getByUserIdAndBiz(request.getUserId(), source);
            if (Objects.isNull(domain)) {
                domain = CollectionDomain.ofInitial();
            }

            // 此处幂等直接返回
            if (domain.isCollecting()) {
                return domain.getId();
            }

            // 收藏
            return collectionStateFactory.getState(domain).collect(request, domain);
        }, getUniqueKey(request));
    }

    @Override
    public Void cancel(CancelCollectionRequest request) {
        return distributeLockSupport.withLock(() -> {
            CollectionDomain domain = loadCollectionDomain(request);
            Preconditions.checkArgument(domain != null, "亲，未查询到收藏信息");
            return collectionStateFactory.getState(domain).cancel(request, domain);
        }, getUniqueKey(request));
    }

    /**
     * 查询收藏域信息
     *
     * @param request
     * @return
     */
    protected CollectionDomain loadCollectionDomain(BaseCollectionRequest request) {
        if (Objects.isNull(request.getCollectionId())) {
            return null;
        }

        // 有用户信息
        if (Objects.nonNull(request.getUserId())) {
            return collectionRepository.getById(request.getUserId(), request.getCollectionId());
        }

        // 直接查询
        return collectionRepository.getById(request.getCollectionId());
    }

    protected String getUniqueKey(CollectRequest request) {
        BizSource source = request.getSource();

        return "collection:" + source.getBizId() + ":" + source.getBizType();
    }

    protected String getUniqueKey(BaseCollectionRequest request) {
        String prefix = "op_collection_";

        if (Objects.nonNull(request.getUserId())) {
            prefix = prefix + request.getUserId() + "_";
        }

        return prefix + request.getCollectionId();
    }

}
